/*
 * CastDRAndroid
 * Copyright (c) 2014 Christian Holm Christensen
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 *
 */
package org.cholm.media.castdr.fragments;

import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import org.cholm.media.castdr.R;
import org.cholm.media.castdr.backend.Category;
import org.cholm.media.castdr.backend.Extractor;
import org.cholm.media.castdr.backend.LiveChannel;
import org.cholm.media.castdr.backend.SubCategory;

import java.util.concurrent.atomic.AtomicInteger;
import org.cholm.media.castdr.LogUtils; import static org.cholm.media.castdr.LogUtils.LOGd;
import static org.cholm.media.castdr.LogUtils.LOGe;

/**
 * A container of the sub-category listing and the detailed view of a
 * sub-category. Note, because we put this fragment into a ViewPager, where the
 * fragments are generated a-head of time, we need to make the sub-view IDs
 * unique to each instance of this fragment. Otherwise, we end up with the next
 * (in the pager order) sub-category view instead of the current one. We
 * implement the function generateViewId here for this. This is re-implemted
 * here from the View since the function View.generateViewId isn't available in
 * all APIs.
 *
 * @author cholm
 */
public class SubFragment extends Fragment {
    /**
     * Debug tag
     */
    private static final String TAG = LogUtils.makeLogTag(SubFragment.class);
    /**
     * Save IDs
     */
    private IdSaver mSaver = new IdSaver(TAG);
    /**
     * Static instance of a integer
     */
    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
    /**
     * Generated ID of the first fragment
     */
    private final int mLeftId = generateViewId();
    /**
     * Generated ID of the second fragment
     */
    private final int mRightId = generateViewId();
    /**
     * Our top-view
     */
    private View mView = null;
    /**
     * Category
     */
    private Category mCategory = null;

    /**
     * Generate a value suitable for use in {@link #setId(int)}. This value will
     * not collide with ID values generated at build time by aapt for R.id.
     *
     * @return a generated ID value
     */
    @SuppressLint("NewApi")
    public static int generateViewId() {
        if (Build.VERSION.SDK_INT < 17) {
            for (; ; ) {
                final int result = sNextGeneratedId.get();
                // aapt-generated IDs have the high byte nonzero; clamp to the
                // range under that.
                int newValue = result + 1;
                if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not
                // 0.
                if (sNextGeneratedId.compareAndSet(result, newValue)) {
                    return result;
                }
            }
        } else {
            return View.generateViewId();
        }
    }

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState != null) {
            mSaver.restore(savedInstanceState);
        }
    }

    /**
     * Create our view
     */
    public View onCreateView(LayoutInflater inflator, ViewGroup container,
                             Bundle savedInstance) {
        int id = mSaver.getId();
        LOGd(TAG, "Creating top view for category " + id);
        if (id < 0) {
            LOGe(TAG, "Arg! no valid id: " + id);
            return null;
        }
        mCategory = Extractor.instance().getList().get(id);
        LOGd(TAG, mCategory.getName());
        mView = inflator.inflate(R.layout.sub_element, container, false);
        View v = mView.findViewById(R.id.listFragment);
        v.setId(mLeftId);
        v = mView.findViewById(R.id.detailFragment);
        if (v != null) v.setId(mRightId);

        if (mCategory.getMap().size() == 1) {
            if (v != null) v.setVisibility(View.GONE);
            showSubCategory(0, false);
        } else {
            showCategory();
        }
        return mView;
    }

    @Override
    public void onDestroyView() {
        LOGd(TAG, "Destroying subFragment: " + mCategory.getName());
        super.onDestroyView();
        mSaver.save();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        LOGd(TAG, "Saving instance state " + mSaver.getId());
        mSaver.save(outState);
        super.onSaveInstanceState(outState);
    }

    void showCategory() {
        CategoryFragment f = new CategoryFragment();
        f.setCategoryId(mSaver.getId());
        f.setListener(new CategoryFragment.OnSubCategoryListener() {
            @Override
            public void onSubCategorySelect(int s) {
                LOGd(TAG, "Selected sub-category " + s);
                showSubCategory(s, true);
            }

        });
        // Add the fragment to the 'fragment_container' FrameLayout
        LOGd(TAG, "Setting fragment for " + mCategory.getName());
        getActivity().getSupportFragmentManager()
                .beginTransaction()
                .replace(mLeftId, f, mCategory.getName() + ":list")
                .commit();
    }

    /**
     * Show the sub-category
     *
     * @param sid SubCategory
     *            @param title Title
     */
    void showSubCategory(int sid, boolean title) {
        FragmentManager fragmentManager =
                getActivity().getSupportFragmentManager();
        SubCategory s = mCategory.getSub(sid);

        if (s == null) {
            fragmentManager.popBackStack();
            return;
        }

        LOGd(TAG, "Showing " + mCategory.getName() + "/" + s.getName());
        int id = mLeftId;

        View v = mView.findViewById(mRightId);
        if (v != null && v.getVisibility() != View.GONE) {
            // Got detail fragment here
            id = mRightId;
            title = false;
        }

        FragmentTransaction fragmentTransaction =
                fragmentManager.beginTransaction();
        Fragment frag = null;
        LOGd(TAG, "Got SubCategory object of class "
                + s.getClass().getSimpleName());
        if (s instanceof LiveChannel) {
            LOGd(TAG, "Creating a LiveFragment for " + s.getName());
            LiveFragment lf = new LiveFragment();
            lf.setTarget(mSaver.getId(), sid);
            lf.setEnableTitle(title);
            frag = lf;
        } else {
            LOGd(TAG, "Creating a SubCategoryFragment for " + s.getName());
            SubCategoryFragment ser = new SubCategoryFragment();
            ser.setEnableTitle(title);
            ser.setTarget(mSaver.getId(), sid);
            frag = ser;
        }
        fragmentTransaction.replace(id,
                frag,
                mCategory.getName() + ":" + s.getName());
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commit();

    }

    /**
     * Get reference to the category
     *
     * @return Category
     */
    public Category getCategory() {
        return mCategory;
    }

    public void setCategoryId(int arg0) {
        mSaver.setId(arg0);
    }
}
// EOF
